package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.attendance.dto.DepartmentOrUserSimpleDTO;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysFunctionDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.entity.ExcelMember;
import com.nineclock.system.entity.ExcelMemberListener;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class SysCompanyUserServiceImpl implements SysCompanyUserService {
    
    @Autowired
    SysDepartmentMapper departmentMapper;
    
    @Autowired
    SysCompanyUserMapper companyUserMapper;
    
    @Autowired
    SysFunctionMapper functionMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;
    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;
    
    @Override
    public SysCompanyUserDTO findCompanyUserByCreateUserId(Long createUserId) {
        SysCompanyUser sysCompanyUser = companyUserMapper.selectById(createUserId);
        if ((sysCompanyUser) != null) {
            SysCompanyUserDTO sysCompanyUserDTO = BeanHelper.copyProperties(sysCompanyUser, SysCompanyUserDTO.class);
            List<SysFunction> functionList = functionMapper.findFunctionByUsername(sysCompanyUserDTO.getUserName(), sysCompanyUserDTO.getCompanyId());
            List<SysFunctionDTO> sysFunctionDTOS = BeanHelper.copyWithCollection(functionList, SysFunctionDTO.class);
            //封装权限
            sysCompanyUserDTO.setFunctions(sysFunctionDTOS);
            //根据企业用户Id去中间表查RoleId
            LambdaQueryWrapper<SysCompanyUserRole> sysCompanyUserMapperLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysCompanyUserMapperLambdaQueryWrapper.eq(SysCompanyUserRole::getCompanyUserId, sysCompanyUser.getId());
            sysCompanyUserMapperLambdaQueryWrapper.eq(SysCompanyUserRole::getCompanyId, sysCompanyUser.getCompanyId());
            List<SysCompanyUserRole> sysCompanyUserRoles = companyUserRoleMapper.selectList(sysCompanyUserMapperLambdaQueryWrapper);
            if (CollectionUtils.isNotEmpty(sysCompanyUserRoles)) {
                //获取RoleId集合
                Set<Long> collect = sysCompanyUserRoles.stream().map(sysCompanyUserRole -> {
                    return sysCompanyUserRole.getRoleId();
                }).collect(Collectors.toSet());
                //查询Role数据
                LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
                sysRoleLambdaQueryWrapper.in(SysRole::getId, collect);
                List<SysRole> roleList = roleMapper.selectList(sysRoleLambdaQueryWrapper);
                //封装角色
                List<SysRoleDTO> sysRoleDTOS = BeanHelper.copyWithCollection(roleList, SysRoleDTO.class);
                sysCompanyUserDTO.setRoles(sysRoleDTOS);
                //封装//当前员工包含的权限（角色，权限）
                sysCompanyUserDTO.setGrantedAuthorities(new ArrayList<>());
            }
            return sysCompanyUserDTO;
        }
        return null;
    }
    
    
    @Override
    public SysCompanyUserDTO queryNameById(Long createUserId) {
        SysCompanyUser sysCompanyUser = companyUserMapper.selectById(createUserId);
        
        return BeanHelper.copyProperties(sysCompanyUser,SysCompanyUserDTO.class);
    }
    
    @Override
    public List<SysCompanyUserDTO> queryCompanyMemberList() {
        //获取企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //查询当前企业的员工列表
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        wrapper.eq(SysCompanyUser::getEnable, 1);
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);
        //如果不为null， 转换为dto 并返回
        if (CollectionUtil.isNotEmpty(companyUserList)) {
            List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
            return companyUserDTOList;
        }
        return null;
    }
    
    @Override
    public PageResult<SysCompanyUserDTO> members(Integer page, Integer pageSize, String keyword, Long departmentId) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        //keyword  关键词  模糊查询
        if (keyword != null) {
            wrapper.and(wrapper1 -> {
                wrapper1.like(SysCompanyUser::getUserName, keyword)
                    .or().like(SysCompanyUser::getWorkNumber, keyword)
                    .or().like(SysCompanyUser::getMobile, keyword);
            });
        }
        //departmentId = 10009 查询该部门的员工信息,  查询该部门的子部门id集合
        List<Long> ids = new ArrayList<>();
        if (departmentId != 0) {
            ids.add(departmentId);
        }
        //查询子部门id
        this.queryChildDepartmentIds(ids, departmentId);
        wrapper.in(SysCompanyUser::getDepartmentId, ids);
        //创建Page对象
        Page<SysCompanyUser> companyUserPage = new Page<>(page, pageSize);
        //分页查询
        companyUserPage = companyUserMapper.selectPage(companyUserPage, wrapper);
        //获取数据列表
        List<SysCompanyUser> records = companyUserPage.getRecords();
        return new PageResult(
            companyUserPage.getTotal(),
            companyUserPage.getPages(),
            BeanHelper.copyWithCollection(records, SysCompanyUserDTO.class));
    }
    
    @Autowired
    SysRoleMapper roleMapper;
    
    @Override
    public void importData(MultipartFile excelFile) throws IOException {
        EasyExcel.read(excelFile.getInputStream(), ExcelMember.class, new ExcelMemberListener(this))
            .sheet(0) //读取第 0个工作表
            .doRead(); //执行 读 操作
    }
    
    @Autowired
    SysUserMapper userMapper;
    
    @Override
    public void handleParsedData(List<ExcelMember> list) {
        if (CollectionUtil.isNotEmpty(list)) {
            for (ExcelMember excelMember : list) {
                //判断手机号和邮箱是否 唯一
                LambdaQueryWrapper<SysUser> userQw = new LambdaQueryWrapper<>();
                userQw.eq(SysUser::getMobile, excelMember.getMobile())
                    .or().eq(SysUser::getEmail, excelMember.getEmail());
                Integer count = userMapper.selectCount(userQw);
                if (count > 0) {
                    throw new NcException(ResponseEnum.USER_MOBILE_EMAIL_EXISTS);
                }
                //判断工号 是否唯一
                LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
                companyUserQw.eq(SysCompanyUser::getWorkNumber, excelMember.getWorkNumber());
                companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
                Integer count1 = companyUserMapper.selectCount(companyUserQw);
                if (count1 > 0) {
                    throw new NcException(ResponseEnum.WROK_NUM_EXISTS);
                }
                //保存用户信息
                SysUser user = new SysUser();
                user.setUsername(excelMember.getName());
                user.setMobile(excelMember.getMobile());
                user.setEmail(excelMember.getEmail());
                user.setPassword(new BCryptPasswordEncoder().encode("123456"));
                user.setStatus((short) 1);
                user.setCreateTime(new Date());
                user.setLastLoginCompanyId(CurrentUserHolder.get().getCompanyId());
                userMapper.insert(user);
                //保存员工信息
                SysCompanyUser companyUser = new SysCompanyUser();
                companyUser.setUserId(user.getId());
                companyUser.setUserName(excelMember.getName());
                companyUser.setMobile(excelMember.getMobile());
                //设置部门信息: 先查， 再存
                if (StrUtil.isNotEmpty(excelMember.getDepartmentName())) {
                    //根据部门名称， 先查询对应的部门信息
                    LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
                    departmentQw.eq(SysDepartment::getName, excelMember.getDepartmentName());
                    departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
                    SysDepartment department = departmentMapper.selectOne(departmentQw);
                    if (department != null) {
                        companyUser.setDepartmentId(department.getId());
                        companyUser.setDepartmentName(department.getName());
                    }
                }
                companyUser.setPost(excelMember.getPosition());
                companyUser.setWorkNumber(excelMember.getWorkNumber());
                companyUser.setEmail(excelMember.getEmail());
                companyUser.setOfficeAddress(excelMember.getWorkAddr());
                companyUser.setRemark(excelMember.getDesc());
                companyUser.setTimeEntry(excelMember.getEntryTime());
                companyUser.setEnable((short) ("可用".equals(excelMember.getEnable()) ? 1 : 0));
                //新增员工
                companyUserMapper.insert(companyUser);
                //维护用户和角色的中间表
                //根据角色名称，查询角色对象
                LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
                roleQw.eq(SysRole::getCompanyId, CurrentUserHolder.get().getCompanyId());
                roleQw.eq(SysRole::getRoleDesc, excelMember.getRoleName());
                SysRole role = roleMapper.selectOne(roleQw);
                if (role != null) {
                    SysCompanyUserRole companyUserRole = new SysCompanyUserRole();
                    companyUserRole.setCompanyUserId(companyUser.getId());
                    companyUserRole.setCompanyId(CurrentUserHolder.get().getCompanyId());
                    companyUserRole.setRoleId(role.getId());
                    //保存员工和角色的关系
                    companyUserRoleMapper.insert(companyUserRole);
                }
            }
        }
    }
    
    @Override
    public SysCompanyUserDTO queryOne(String mobile) {
        if (mobile == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getMobile, mobile);
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        if (companyUser != null) {
            return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        }
        return null;
    }
    
    @Override
    public Integer queryUserCountByDepartmentIds(List<Long> departmentIds) {
        List<Long> ids = new ArrayList<>();
        ids.addAll(departmentIds);
        //查询这些部门 的子部门信息
        if (departmentIds != null) {
            for (Long departmentId : departmentIds) {
                this.queryChildDepartmentIds(ids, departmentId);
            }
        }
        //统计员工的数量
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        //判断 员工所在部门是否在集合中
        wrapper.in(SysCompanyUser::getDepartmentId, ids);
        Integer count = companyUserMapper.selectCount(wrapper);
        return count;
    }
    
    /**
     * 查询 指定部门的 下级部门及员工信息
     *
     * @param departmentId
     * @param includeMember
     * @return
     */
    @Override
    public List<DepartmentOrUserSimpleDTO> querySimpleDepartment(Long departmentId, Integer includeMember) {
        List<DepartmentOrUserSimpleDTO> departmentOrUserSimpleDTOList = new ArrayList<>();
        //健壮性的判断
        if (departmentId == null || includeMember == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //先查询 下级部门信息
        LambdaQueryWrapper<SysDepartment> departmentQw = new LambdaQueryWrapper<>();
        departmentQw.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        departmentQw.eq(SysDepartment::getParentId, departmentId);
        //查询获取 下级部门列表
        List<SysDepartment> departmentList = departmentMapper.selectList(departmentQw);
        if (CollectionUtil.isNotEmpty(departmentList)) {
            for (SysDepartment department : departmentList) {
                //转换为 simple 对象
                DepartmentOrUserSimpleDTO departmentSimpleDTO = new DepartmentOrUserSimpleDTO();
                departmentSimpleDTO.setId(department.getId());
                departmentSimpleDTO.setName(department.getName());
                departmentSimpleDTO.setType(1); //类型为部门
                departmentOrUserSimpleDTOList.add(departmentSimpleDTO);
            }
        }
        //includeMember = 0 说明包含员工信息， 查询员工列表
        if (includeMember == 0) {
            LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
            companyUserQw.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
            companyUserQw.eq(SysCompanyUser::getDepartmentId, departmentId);
            //获取该部门的员工信息
            List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserQw);
            if (CollectionUtil.isNotEmpty(companyUserList)) {
                for (SysCompanyUser companyUser : companyUserList) {
                    DepartmentOrUserSimpleDTO userSimpleDTO = new DepartmentOrUserSimpleDTO();
                    userSimpleDTO.setId(companyUser.getId());
                    userSimpleDTO.setName(companyUser.getUserName());
                    userSimpleDTO.setType(2);
                    //添加到集合中
                    departmentOrUserSimpleDTOList.add(userSimpleDTO);
                }
            }
        }
        return departmentOrUserSimpleDTOList;
    }
    
    @Autowired
    SysCompanyMapper companyMapper;
    
    @Override
    public SysCompanyUserDTO queryAdminByCompanyId(Long companyId) {
        SysCompanyUser companyUser = companyMapper.queryCurrentAdmin(companyId);
        if (companyUser != null) {
            return BeanHelper.copyProperties(companyUser, SysCompanyUserDTO.class);
        }
        return null;
    }
    
    @Override
    public List<SysCompanyUserDTO> queryAllUserByCompanyId(Long companyId) {
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getCompanyId, companyId);
        wrapper.eq(SysCompanyUser::getEnable, 1);
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(companyUserList)) {
            return BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
        }
        return null;
    }
    
    @Override
    public List<SysCompanyUserDTO> queryCompanyUser(Long userId, Long companyId) {
        //健壮性判断
        if (userId == null && companyId == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        //根据用户id和 企业id 查询员工信息
        LambdaQueryWrapper<SysCompanyUser> companyUserQw = new LambdaQueryWrapper<>();
        if (userId != null) {
            companyUserQw.eq(SysCompanyUser::getUserId, userId);
        }
        if (companyId != null) {
            companyUserQw.eq(SysCompanyUser::getCompanyId, companyId);
        }
        //必须 已经审核加入 企业的员工
        companyUserQw.eq(SysCompanyUser::getEnable, 1);
        //获取 用户和企业对应的员工列表
        List<SysCompanyUser> companyUserList = companyUserMapper.selectList(companyUserQw);
        if (CollectionUtil.isNotEmpty(companyUserList)) {
            List<SysCompanyUserDTO> companyUserDTOList = BeanHelper.copyWithCollection(companyUserList, SysCompanyUserDTO.class);
            //循环 员工列表， 查询每个员工对应的角色列表
            for (SysCompanyUserDTO companyUserDTO : companyUserDTOList) {
                List<SysRole> roleList = roleMapper.queryRoleListByCompanyUserId(companyUserDTO.getId(), companyUserDTO.getCompanyId());
                if (CollectionUtil.isNotEmpty(roleList)) {
                    companyUserDTO.setRoles(BeanHelper.copyWithCollection(roleList, SysRoleDTO.class));
                }
            }
            return companyUserDTOList;
        }
        return null;
    }
    
    @Override
    public String queryDepartmentName(String userName, Long companyId) {
        String departmentName = companyUserMapper.queryDepartmentName(userName, companyId);
        return departmentName;
    }
    
    private void queryChildDepartmentIds(List<Long> ids, Long departmentId) {
        LambdaQueryWrapper<SysDepartment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDepartment::getCompanyId, CurrentUserHolder.get().getCompanyId());
        wrapper.eq(SysDepartment::getParentId, departmentId);
        //子部门列表
        List<SysDepartment> departmentList = departmentMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(departmentList)) {
            //把部门列表集合转换为 部门id集合
            List<Long> departmentIds = departmentList.stream().map(department -> {
                return department.getId();
            }).collect(Collectors.toList());
            //把部门id 添加到 集合中
            ids.addAll(departmentIds);
            //循环部门id， 再次查询子部门
            for (Long id : departmentIds) {
                this.queryChildDepartmentIds(ids, id);
            }
        }
    }
}
